<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="../">
<head>
  <meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Dynamic object attributes &mdash; The Logtalk Handbook v3.93.0-b01 documentation</title>
      <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
      <link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094" />
      <link rel="stylesheet" type="text/css" href="../_static/css/custom.css?v=396eccfe" />

  
  <!--[if lt IE 9]>
    <script src="../_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script src="../_static/jquery.js?v=5d32c60e"></script>
        <script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
        <script src="../_static/documentation_options.js?v=c8100655"></script>
        <script src="../_static/doctools.js?v=9a2dae69"></script>
        <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
    <script src="../_static/js/theme.js"></script>
    <!-- begin favicon -->
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
    <link rel="manifest" href="/site.webmanifest" />
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
    <meta name="msapplication-TileColor" content="#355b95" />
    <meta name="theme-color" content="#ffffff" />
    <!-- end favicon -->
    
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="A reflective class-based system" href="reflection.html" />
    <link rel="prev" title="List predicates" href="lists.html" />
   
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >

          
          
          <a href="../index.html" class="icon icon-home">
            The Logtalk Handbook
              <img src="../_static/logtalk.gif" class="logo" alt="Logo"/>
          </a>
              <div class="version">
                3.93.0
              </div>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
    
              <p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../userman/index.html">User Manual</a></li>
<li class="toctree-l1"><a class="reference internal" href="../refman/index.html">Reference Manual</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Tutorial</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="lists.html">List predicates</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Dynamic object attributes</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#defining-a-category">Defining a category</a></li>
<li class="toctree-l3"><a class="reference internal" href="#importing-the-category">Importing the category</a></li>
<li class="toctree-l3"><a class="reference internal" href="#summary">Summary</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="reflection.html">A reflective class-based system</a></li>
<li class="toctree-l2"><a class="reference internal" href="profiling.html">Profiling programs</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../devtools/index.html">Developer Tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../libraries/index.html">Libraries</a></li>
<li class="toctree-l1"><a class="reference internal" href="../ports/index.html">Ports</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributions/index.html">Contributions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../bibliography.html">Bibliography</a></li>
<li class="toctree-l1"><a class="reference internal" href="../genindex.html">Index</a></li>
</ul>

    <p class="caption"><span class="caption-text">External Contents</span></p>
    <ul>
    <li class="toctree-l1"><a class="reference internal" href="../../apis/index.html">APIs</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://logtalk.org">Logtalk website</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://github.com/LogtalkDotOrg/logtalk3">GitHub repo</a></li>
    </ul>
  
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../index.html">The Logtalk Handbook</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
          <li class="breadcrumb-item"><a href="index.html">Tutorial</a></li>
      <li class="breadcrumb-item active">Dynamic object attributes</li>
      <li class="wy-breadcrumbs-aside">
              <a href="https://github.com/LogtalkDotOrg/logtalk3/blob/master/docs/handbook/sources/tutorial/attributes.rst" class="fa fa-github"> Edit on GitHub</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section id="dynamic-object-attributes">
<h1>Dynamic object attributes<a class="headerlink" href="#dynamic-object-attributes" title="Link to this heading"></a></h1>
<p>In this example, we will illustrate the use of:</p>
<ul class="simple">
<li><p>categories</p></li>
<li><p>category predicates</p></li>
<li><p>dynamic predicates</p></li>
</ul>
<p>by defining a category that implements a set of predicates for handling
dynamic object attributes.</p>
<section id="defining-a-category">
<span id="category"></span><h2>Defining a category<a class="headerlink" href="#defining-a-category" title="Link to this heading"></a></h2>
<p>We want to define a set of predicates to handle dynamic object
attributes. We need public predicates to set, get, and delete
attributes, and a private dynamic predicate to store the attribute
values. Let us name these predicates <code class="docutils literal notranslate"><span class="pre">set_attribute/2</span></code> and
<code class="docutils literal notranslate"><span class="pre">get_attribute/2</span></code>, for getting and setting an attribute value,
<code class="docutils literal notranslate"><span class="pre">del_attribute/2</span></code> and <code class="docutils literal notranslate"><span class="pre">del_attributes/2</span></code>, for deleting attributes,
and <code class="docutils literal notranslate"><span class="pre">attribute_/2</span></code>, for storing the attributes values.</p>
<p>But we do not want to encapsulate these predicates in an object. Why?
Because they are a set of useful, closely related, predicates that may
be used by several, unrelated, objects. If defined at an object level,
we would be constrained to use inheritance in order to have the
predicates available to other objects. Furthermore, this could force us
to use multi-inheritance or to have some kind of generic root object
containing all kinds of possible useful predicates.</p>
<p>For this kind of situation, Logtalk enables the programmer to
encapsulate the predicates in a <em>category</em>, so that they can be used in
any object. A category is a Logtalk entity, at the same level as objects
and protocols. It can contain predicate directives and predicate
definitions. Category predicates can be imported by any object, without
code duplication and without resorting to inheritance.</p>
<p>When defining category predicates, we need to remember that a category
can be imported by more than one object. Thus, calls to the built-in
methods that handle the private dynamic predicate (such as
<a class="reference internal" href="../refman/methods/assertz_1.html#methods-assertz-1"><span class="std std-ref">assertz/1</span></a> or <a class="reference internal" href="../refman/methods/retract_1.html#methods-retract-1"><span class="std std-ref">retract/1</span></a>) must be made
either in the context of <em>self</em>, using the <em>message to self</em> control
structure, <a class="reference internal" href="../refman/control/send_to_self_1.html#control-send-to-self-1"><span class="std std-ref">(::)/1</span></a>, or in
the context of <em>this</em> (i.e., in the context of the object importing the
category). This way, we ensure that when we call one of the attribute
predicates on an object, the intended object own definition of
<code class="docutils literal notranslate"><span class="pre">attribute_/2</span></code> will be used. The predicate definitions are
straightforward. For example, if opting to store the attributes in
<em>self</em>:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">category</span>(attributes).

<span class="p">    :- </span><span class="k">public</span>(set_attribute<span class="o">/</span><span class="m">2</span>).
<span class="p">    :- </span><span class="k">mode</span>(set_attribute(<span class="o">+</span>nonvar, <span class="o">+</span>nonvar), one).

<span class="p">    :- </span><span class="k">public</span>(get_attribute<span class="o">/</span><span class="m">2</span>).
<span class="p">    :- </span><span class="k">mode</span>(get_attribute(<span class="o">?</span>nonvar, <span class="o">?</span>nonvar), zero_or_more).

<span class="p">    :- </span><span class="k">public</span>(del_attribute<span class="o">/</span><span class="m">2</span>).
<span class="p">    :- </span><span class="k">mode</span>(del_attribute(<span class="o">?</span>nonvar, <span class="o">?</span>nonvar), zero_or_more).

<span class="p">    :- </span><span class="k">public</span>(del_attributes<span class="o">/</span><span class="m">2</span>).
<span class="p">    :- </span><span class="k">mode</span>(del_attributes(<span class="o">@</span>term, <span class="o">@</span>term), one).

<span class="p">    :- </span><span class="k">private</span>(attribute_<span class="o">/</span><span class="m">2</span>).
<span class="p">    :- </span><span class="k">mode</span>(attribute_(<span class="o">?</span>nonvar, <span class="o">?</span>nonvar), zero_or_more).
<span class="p">    :- </span><span class="k">dynamic</span>(attribute_<span class="o">/</span><span class="m">2</span>).

    set_attribute(<span class="nv">Attribute</span>, <span class="nv">Value</span>)<span class="o">:-</span>
        <span class="o">::</span><span class="k">retractall</span>(attribute_(<span class="nv">Attribute</span>, <span class="nv">_</span>)),
        <span class="o">::</span><span class="k">assertz</span>(attribute_(<span class="nv">Attribute</span>, <span class="nv">Value</span>)).

    get_attribute(<span class="nv">Attribute</span>, <span class="nv">Value</span>)<span class="o">:-</span>
        <span class="o">::</span>attribute_(<span class="nv">Attribute</span>, <span class="nv">Value</span>).

    del_attribute(<span class="nv">Attribute</span>, <span class="nv">Value</span>)<span class="o">:-</span>
        <span class="o">::</span><span class="k">retract</span>(attribute_(<span class="nv">Attribute</span>, <span class="nv">Value</span>)).

    del_attributes(<span class="nv">Attribute</span>, <span class="nv">Value</span>)<span class="o">:-</span>
        <span class="o">::</span><span class="k">retractall</span>(attribute_(<span class="nv">Attribute</span>, <span class="nv">Value</span>)).

<span class="p">:- </span><span class="k">end_category</span>.
</pre></div>
</div>
<p>The alternative, opting to store the attributes on <em>this</em>, is
similar: just delete the <code class="docutils literal notranslate"><span class="pre">(::)/1</span></code> operator from the code above.</p>
<p>We have two new directives, <a class="reference internal" href="../refman/directives/category_1_4.html#directives-category-1-4"><span class="std std-ref">category/1-4</span></a> and
<a class="reference internal" href="../refman/directives/end_category_0.html#directives-end-category-0"><span class="std std-ref">end_category/0</span></a>, that
encapsulate the category code. If needed, we can put the predicate
directives inside a protocol that will be implemented by the category:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">category</span>(attributes,
    <span class="k">implements</span>(attributes_protocol)).

    ...

<span class="p">:- </span><span class="k">end_category</span>.
</pre></div>
</div>
<p>Any protocol can be implemented by either an object, a category, or
both.</p>
</section>
<section id="importing-the-category">
<span id="importing"></span><h2>Importing the category<a class="headerlink" href="#importing-the-category" title="Link to this heading"></a></h2>
<p>We reuse a category’s predicates by importing them into an object:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(person,
    <span class="k">imports</span>(attributes)).

    ...

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>After compiling and loading this object and our category, we can now try
queries like:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- person::set_attribute(name, paulo).

yes

| ?- person::set_attribute(gender, male).

yes

| ?- person::get_attribute(Attribute, Value).

Attribute = name, Value = paulo ;
Attribute = gender, Value = male ;
no
</pre></div>
</div>
</section>
<section id="summary">
<h2>Summary<a class="headerlink" href="#summary" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p>Categories are similar to objects: we just write our predicate
directives and definitions bracketed by opening and ending category
directives.</p></li>
<li><p>An object reuses a category by importing it. The imported predicates
behave as if they have been defined in the object itself.</p></li>
<li><p>When do we use a category instead of an object? Whenever we have a
set of closely related predicates that we want to reuse in several,
unrelated, objects without being constrained by inheritance
relations. Thus, categories can be interpreted as object building
components.</p></li>
</ul>
</section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="lists.html" class="btn btn-neutral float-left" title="List predicates" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="reflection.html" class="btn btn-neutral float-right" title="A reflective class-based system" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 1998-2025, Paulo Moura.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>